package control;

import java.awt.event.*;
import java.util.*;
import java.util.Map.Entry;

import javax.swing.JFrame;

import vista.*;
import modelo.*;
import componentes.*;

public class Ejecutable {

	private static Interfaz frame;

	// Componentes
	private static DepositoMonedas deposito100, deposito200, deposito500;
	private static Ingredientario ing;
	private static Recetario rec;
	private static Alarmario alar;

	// Entidades
	private static Ingrediente agua, cafe, azucar, vaso;
	private static Receta tinto, tintoCargado;

	// Variables

	private static int monedas100, monedas200, monedas500, suma;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		try {
			frame = new Interfaz();
			frame.setLocationRelativeTo(null);
			frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
			frame.setVisible(true);
		} catch (Exception e) {
			e.printStackTrace();
		}

		arrancarMaquina();
		eventos();
	}

	/**
	 * 
	 * Por ahora se inicializa localmente, se requiere inicializar con los datos
	 * del archivo plano
	 * 
	 **/

	public static void arrancarMaquina() {

		// Otras Variables

		monedas100 = 0;
		monedas200 = 0;
		monedas500 = 0;

		// Ingredientes (Del Plano)
		agua = new Ingrediente("Agua", (double) 500, (double) 50, (double) 1000);
		cafe = new Ingrediente("Cafe", (double) 500, (double) 50, (double) 1000);
		azucar = new Ingrediente("Azucar", (double) 500, (double) 50,
				(double) 1000);
		vaso = new Ingrediente("Vaso", (double) 50, (double) 5, (double) 200);

		// Recetas (Del Plano)
		HashMap<Ingrediente, Double> ingTinto = new HashMap<Ingrediente, Double>();

		ingTinto.put(agua, (double) 100);
		ingTinto.put(cafe, (double) 10);
		ingTinto.put(azucar, (double) 10);
		ingTinto.put(vaso, (double) 1);

		tinto = new Receta("Tinto", 800, ingTinto);

		HashMap<Ingrediente, Double> ingTintoCargado = new HashMap<Ingrediente, Double>();

		ingTintoCargado.put(agua, (double) 100);
		ingTintoCargado.put(cafe, (double) 30);
		ingTintoCargado.put(azucar, (double) 10);
		ingTintoCargado.put(vaso, (double) 1);

		tintoCargado = new Receta("Tinto Cargado", 1000, ingTintoCargado);

		// Listas

		ArrayList<Receta> listaRecetas = new ArrayList<Receta>();
		listaRecetas.add(tinto);
		listaRecetas.add(tintoCargado);

		HashMap<Ingrediente, Double> listaIngredientes = new HashMap<Ingrediente, Double>();
		listaIngredientes.put(cafe, (double) 600);
		listaIngredientes.put(agua, (double) 600);
		listaIngredientes.put(azucar, (double) 600);
		listaIngredientes.put(vaso, (double) 200);

		// DepositoMonedas (Del Plano)
		deposito100 = new DepositoMonedas("100", 12, 10, 5, 30);
		deposito200 = new DepositoMonedas("200", 12, 10, 5, 30);
		deposito500 = new DepositoMonedas("500", 12, 10, 5, 30);

		// Componentes

		ing = new Ingredientario(listaIngredientes);
		rec = new Recetario(listaRecetas);
		alar = new Alarmario();

		// Interfaz
		actualizarRecetasCombo();
		actualizarRecetasGraf();
		actualizarInsumosGraf();
		actualizarAlarmasGraf();

	}

	public static void eventos() {

		frame.getBtnIngresar100().addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				frame.getTextAreaSaldo().setText(
						String.valueOf(Integer.parseInt(frame
								.getTextAreaSaldo().getText()) + 100));
				suma += 100;
				deposito100.setCantidad(deposito100.getCantidad() + 1);
				actualizarInsumosGraf();

			}
		});

		frame.getBtnIngresar200().addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				frame.getTextAreaSaldo().setText(
						String.valueOf(Integer.parseInt(frame
								.getTextAreaSaldo().getText()) + 200));
				suma += 200;
				deposito200.setCantidad(deposito200.getCantidad() + 1);
				actualizarInsumosGraf();

			}
		});

		frame.getBtnIngresar500().addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				frame.getTextAreaSaldo().setText(
						String.valueOf(Integer.parseInt(frame
								.getTextAreaSaldo().getText()) + 500));
				suma += 500;
				deposito500.setCantidad(deposito500.getCantidad() + 1);
				actualizarInsumosGraf();

			}
		});

		frame.getBtnCancelar().addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				frame.getTextAreaSaldo().setText("0");

				if (suma > 0) {

					frame.getTextAreaDevuelta().setText(
							frame.getTextAreaDevuelta().getText()
									+ "Se devolvio: " + suma + "\n");

					devolverMonedas();
					verificarMonedas();

					suma = 0;
					monedas100 = 0;
					monedas200 = 0;
					monedas500 = 0;

				}

			}
		});

		frame.getBtnVerificar().addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				int precio = 0;

				for (int i = 0; i < rec.getListaRecetas().size(); i++) {

					if (frame
							.getComboBoxProducto()
							.getSelectedItem()
							.equals(rec.getListaRecetas().get(i)
									.getDescripcion())) {
						precio = rec.getListaRecetas().get(i).getValor();
					}

				}

				frame.getTextAreaInfo().setText(
						frame.getTextAreaInfo().getText()
								+ "El producto cuesta: " + precio + "\n");
				frame.getTextAreaInfo().repaint();
			}
		});

		frame.getBtnOrdenar().addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				int precio = 0;
				Receta temp = null;

				for (int i = 0; i < rec.getListaRecetas().size(); i++) {

					temp = rec.getListaRecetas().get(i);

					if (frame.getComboBoxProducto().getSelectedItem()
							.equals(temp.getDescripcion())) {
						precio = rec.getListaRecetas().get(i).getValor();

						if (Integer.valueOf(frame.getTextAreaSaldo().getText()) >= precio) {

							frame.getTextAreaInfo().setText(
									frame.getTextAreaInfo().getText()
											+ "Se ordeno: "
											+ frame.getComboBoxProducto()
													.getSelectedItem() + "\n");

							frame.getTextAreaSaldo().setText(
									Integer.valueOf(frame.getTextAreaSaldo()
											.getText()) - precio + "");

							suma -= precio;

							disminuirInsumos(temp, frame.getComboBoxProducto()
									.getSelectedItem().toString());

							devolverMonedas();
							verificarMonedas();
							verificarProductos();

							monedas100 = 0;
							monedas200 = 0;
							monedas500 = 0;

							frame.getTextAreaSaldo().setText("0");

						} else {
							frame.getTextAreaInfo().setText(
									frame.getTextAreaInfo().getText()
											+ "Saldo insuficiente \n");

						}

					}

				}

			}

		});

		frame.getBtnMantenimiento().addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				// Enviar Alarma por SCA

				Alarma temp = new Alarma("Mantenimiento",
						"Se requiere mantenimiento", new Date());

				frame.getTextAreaAlarmas().setText(
						frame.getTextAreaAlarmas().getText()
								+ "Se genero una alarma de: " + temp.getTipo()
								+ "\n");

				frame.setEnabled(false);

			}
		});

		frame.getComboBoxProducto().addItemListener(new ItemListener() {

			@Override
			public void itemStateChanged(ItemEvent e) {
				// TODO Auto-generated method stub

			}
		});

	}

	public static void devolverMonedas() {
		// Metodo para devolver monedas

		if (suma / 500 > 0) {
			monedas500 += (int) suma / 500;
			deposito500.setCantidad(deposito500.getCantidad() - monedas500);
			suma -= 500 * ((int) suma / 500);

		}

		if (suma / 200 > 0) {

			monedas200 += (int) suma / 200;
			deposito200.setCantidad(deposito200.getCantidad() - monedas200);
			suma -= 200 * ((int) suma / 200);

		}
		if (suma / 100 > 0) {
			monedas100 += (int) suma / 100;
			deposito100.setCantidad(deposito100.getCantidad() - monedas100);
			suma -= 100 * ((int) suma / 100);

		}

		frame.getTextAreaDevuelta().setText(
				frame.getTextAreaDevuelta().getText() + "Se devolvieron: "
						+ monedas500 + " monedas de 500, " + monedas200
						+ " monedas de 200 y " + monedas100
						+ " monedas de 100 \n");

		actualizarInsumosGraf();

	}

	public static void actualizarRecetasGraf() {

		frame.getTextAreaRecetas().setText("");

		// Llenar Recetas

		Iterator<Receta> it2 = rec.getListaRecetas().iterator();
		while (it2.hasNext()) {

			Receta temp = it2.next();
			frame.getTextAreaRecetas().setText(
					frame.getTextAreaRecetas().getText()
							+ temp.getDescripcion() + "\n");

		}

	}

	public static void actualizarInsumosGraf() {

		frame.getTextAreaInsumos().setText("");

		// LLenar Insumos
		Iterator<Entry<Ingrediente, Double>> it = ing.getListaIngredientes()
				.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry<Ingrediente, Double> pareja = (Map.Entry<Ingrediente, Double>) it
					.next();

			frame.getTextAreaInsumos().setText(
					frame.getTextAreaInsumos().getText()
							+ pareja.getKey().getNombre() + ": "
							+ pareja.getValue() + "\n");

		}

		frame.getTextAreaInsumos().setText(
				frame.getTextAreaInsumos().getText() + "Deposito "
						+ deposito100.getTipo() + ": "
						+ deposito100.getCantidad() + "\n");
		frame.getTextAreaInsumos().setText(
				frame.getTextAreaInsumos().getText() + "Deposito "
						+ deposito200.getTipo() + ": "
						+ deposito200.getCantidad() + "\n");
		frame.getTextAreaInsumos().setText(
				frame.getTextAreaInsumos().getText() + "Deposito "
						+ deposito500.getTipo() + ": "
						+ deposito500.getCantidad() + "\n");

	}

	public static void actualizarAlarmasGraf() {

		frame.getTextAreaAlarmas().setText("");

	}

	public static void disminuirInsumos(Receta r, String nombreR) {

		Iterator<Entry<Ingrediente, Double>> it = r.getListaIngredientes()
				.entrySet().iterator();

		while (it.hasNext()) {
			Map.Entry<Ingrediente, Double> pareja = (Map.Entry<Ingrediente, Double>) it
					.next();

			Iterator<Entry<Ingrediente, Double>> itIng = ing
					.getListaIngredientes().entrySet().iterator();

			while (itIng.hasNext()) {
				Map.Entry<Ingrediente, Double> pareja2 = (Map.Entry<Ingrediente, Double>) itIng
						.next();

				if (pareja.getKey().equals(pareja2.getKey())) {

					pareja2.setValue(pareja2.getValue() - pareja.getValue());
					// Modificar XML
				}
			}

		}

		actualizarInsumosGraf();

	}

	public static void verificarMonedas() {

		// Alarma (Generada por Uso)

		if (deposito100.getCantidad() <= deposito100.getMinimo()
				&& deposito100.getCantidad() > deposito100.getCritico()) {

			Alarma alMon = new Alarma("100", "Faltan monedas de 100",
					new Date());
			if (!alar.getListaAlarmas().contains(alMon)) {
				alar.getListaAlarmas().add(alMon);

				// Enviar SCA

				frame.getTextAreaAlarmas().setText(
						frame.getTextAreaAlarmas().getText()
								+ "Se genero una alarma de: " + alMon.getTipo()
								+ "\n");

			}
		}

		if (deposito100.getCantidad() <= deposito100.getCritico()) {

			Alarma alMon = new Alarma("Critico100",
					"ESTADO CRITICO: Faltan monedas de 100", new Date());
			alar.getListaAlarmas().add(alMon);

			// Enviar SCA

			frame.getTextAreaAlarmas().setText(
					frame.getTextAreaAlarmas().getText()
							+ "Se genero una alarma de: " + alMon.getTipo()
							+ "\n");

			frame.setEnabled(false);

		}

		if (deposito200.getCantidad() <= deposito200.getMinimo()
				&& deposito200.getCantidad() > deposito200.getCritico()) {

			Alarma alMon = new Alarma("200", "Faltan monedas de 200",
					new Date());

			if (!alar.getListaAlarmas().contains(alMon)) {
				alar.getListaAlarmas().add(alMon);

				// Enviar SCA

				frame.getTextAreaAlarmas().setText(
						frame.getTextAreaAlarmas().getText()
								+ "Se genero una alarma de: " + alMon.getTipo()
								+ "\n");

			}
		}

		if (deposito200.getCantidad() <= deposito200.getCritico()) {

			Alarma alMon = new Alarma("Critico200",
					"ESTADO CRITICO: Faltan monedas de 200", new Date());
			alar.getListaAlarmas().add(alMon);

			// Enviar SCA

			frame.getTextAreaAlarmas().setText(
					frame.getTextAreaAlarmas().getText()
							+ "Se genero una alarma de: " + alMon.getTipo()
							+ "\n");

			frame.setEnabled(false);

		}

		if (deposito500.getCantidad() <= deposito500.getMinimo()
				&& deposito500.getCantidad() > deposito500.getCritico()) {

			Alarma alMon = new Alarma("500", "Faltan monedas de 500",
					new Date());
			if (!alar.getListaAlarmas().contains(alMon)) {
				alar.getListaAlarmas().add(alMon);

				// Enviar SCA

				frame.getTextAreaAlarmas().setText(
						frame.getTextAreaAlarmas().getText()
								+ "Se genero una alarma de: " + alMon.getTipo()
								+ "\n");

			}
		}
		if (deposito500.getCantidad() <= deposito500.getCritico()) {

			Alarma alMon = new Alarma("Critico500",
					"ESTADO CRITICO: Faltan monedas de 500", new Date());
			alar.getListaAlarmas().add(alMon);

			// Enviar SCA

			frame.getTextAreaAlarmas().setText(
					frame.getTextAreaAlarmas().getText()
							+ "Se genero una alarma de: " + alMon.getTipo()
							+ "\n");

			frame.setEnabled(false);

		}

	}

	public static void verificarProductos() {

		Iterator<Entry<Ingrediente, Double>> itIng = ing.getListaIngredientes()
				.entrySet().iterator();

		while (itIng.hasNext()) {
			Map.Entry<Ingrediente, Double> pareja2 = (Map.Entry<Ingrediente, Double>) itIng
					.next();

			if (pareja2.getValue() <= pareja2.getKey().getMinimo()
					&& pareja2.getValue() > pareja2.getKey().getCritico()) {

				Alarma alIng = new Alarma(pareja2.getKey().getNombre(),
						"Falta un ingrediente", new Date());

				if (!alar.getListaAlarmas().contains(alIng)) {

					alar.getListaAlarmas().add(alIng);
					// Enviar SCA

					frame.getTextAreaAlarmas().setText(
							frame.getTextAreaAlarmas().getText()
									+ "Se genero una alarma de: "
									+ alIng.getTipo() + "\n");

				}
			}

			if (pareja2.getValue() <= pareja2.getKey().getCritico()) {

				Alarma alIng = new Alarma("Critico"
						+ pareja2.getKey().getNombre(), "Falta un ingrediente",
						new Date());

				alar.getListaAlarmas().add(alIng);

				// Enviar SCA

				frame.getTextAreaAlarmas().setText(
						frame.getTextAreaAlarmas().getText()
								+ "Se genero una alarma de: " + alIng.getTipo()
								+ "\n");

				frame.setEnabled(false);
			}

		}
	}

	public static void actualizarRecetasCombo() {

		// Reestablece Combobox
		frame.getComboBoxProducto().removeAllItems();

		// LLenar Combo
		for (int i = 0; i < rec.getListaRecetas().size(); i++) {

			frame.getComboBoxProducto().addItem(
					rec.getListaRecetas().get(i).getDescripcion());
		}
	}

	public static void cargarReceta(Receta nuevaR) {

		rec.getListaRecetas().add(nuevaR);
		// Actualizar Archivo Plano

		actualizarRecetasGraf();
		actualizarRecetasCombo();

	}

	public static void abastecer() {

		// Actualizar XML

		// Ingredientes
		Iterator<Entry<Ingrediente, Double>> itIng = ing.getListaIngredientes()
				.entrySet().iterator();

		while (itIng.hasNext()) {
			Map.Entry<Ingrediente, Double> pareja2 = (Map.Entry<Ingrediente, Double>) itIng
					.next();

			pareja2.setValue(pareja2.getKey().getMaximo());
		}

		// Depositos Monedas
		deposito100.setCantidad(20);
		deposito200.setCantidad(20);
		deposito500.setCantidad(20);

		// ResetAlarmas

		alar.setListaAlarmas(new ArrayList<Alarma>());

		actualizarRecetasGraf();
		actualizarInsumosGraf();
		actualizarAlarmasGraf();

	}
}
